/*
 * threadEscuchas.cpp
 *
 *  Created on: 24/10/2010
 *      Author: teledhil
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "comandos.h"
#include "escuchas.h"
#include "consola.h"
#include "comunicacion.h"
#include "variablesGlobales.h"

#define UNUSED(x) ((void)(x))

int reconstruir_mensaje(char *mensaje, char c) {

	//char temp[MAX_LONG_IRC_MESSAGE];

	//strcat (temp, mensaje);
	//strcat(temp, &c);

	if (c == LF) {
		return strlen(mensaje);
	} else if (c != CR) {
		strncat(mensaje, &c, 1);
	}

	return 0;
}

int evaluar_comando(char *linea) {

	static char espacios[] = " \f\n\r\t\v";
	char palabra[BUFFER], *ptCaracter = NULL, *mensaje = NULL;
	bool seguir = true;
	char argumento1[BUFFER], argumento2[BUFFER];
	char *servidor = NULL, /**miNick=NULL,*/*ptr = NULL;
	int numero;
	unsigned int ip;
	int ip1, ip2, ip3, ip4;
	long longitud = 0l;
	char file_dl_path_temp[BUFFER] = "";
	char *name_file, *temp;

	//Inicializa argumento1, argumento2, palabra
	memset(argumento1, '\0', BUFFER);
	memset(argumento2, '\0', BUFFER);
	memset(palabra, '\0', BUFFER);

	ptCaracter = linea;
	/*Comprueba si la primera palabra es el hostname del servidor*/
	if (COLON == (*linea)) {
		/*obtiene la primera palabra de la linea*/
		for (; ((*ptCaracter) != '\0') && seguir; ptCaracter++) {
			if (strchr(espacios, *ptCaracter)) {
				seguir = false;
				ptCaracter--;
			} else {
				/*output_debug("evaluarComando. c=%c", *ptCaracter);*/
			}
		}
		servidor = (char *) calloc(1, (ptCaracter - linea + 1) * sizeof(char));
		strncat(servidor, linea, ptCaracter - linea);
		/*output_debug("evaluarComando. servidor=%s", servidor);*/
	}

	if (sscanf(ptCaracter, "%s", palabra) < 1) {
		output_debug("Recibido mensaje sin comando");
		return 0;
	}

	//Evalua la primera palabra

	//IRC NUMERIC REPLIES
	//*******************
	if (strcmp(palabra, IRC_PING) == 0) {
		numero = sscanf(ptCaracter, "%*s %s %s", argumento1, argumento2);
		if (numero < 1) {
			pong(NULL, NULL);
		} else if (numero < 2) {
			pong(argumento1, NULL);
		} else {
			pong(argumento1, argumento2);
		}

	} else if (strcmp(palabra, RPL_WELCOME) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		if (mensaje) {
			output_program("%s", (mensaje + 1));
		}
		/*ptr = strtok(mensaje, "~@");
		 if (ptr) {
		 ptr = strtok(NULL, "~@");
		 }
		 if (ptr) {
		 strcpy(nick, ptr);
		 output_debug("ptr=%s, Nick=%s", ptr, nick);
		 }
		 miNick=strrchr(ptr,' ');
		 if(miNick) {
		 output_debug("Nick=%s",(miNick+1));
		 }*/

	} else if (strcmp(palabra, RPL_YOURHOST) == 0) {
		if (sscanf(ptCaracter, "%*s %s", argumento1) == 1) {
			strcpy(nick, argumento1);
			output_debug("nick leido=%s, Nick=%s", argumento1, nick);
		}
		mensaje = strpbrk(ptCaracter, ":");
		if (mensaje) {
			output_program("%s", (mensaje + 1));
		}

	} else if (strcmp(palabra, RPL_CREATED) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		if (mensaje) {
			output_program("%s", (mensaje + 1));
		}

	} else if (strcmp(palabra, RPL_MYINFO) == 0) {
		if (sscanf(ptCaracter, "%*s %*s %*s %*s %s %s", argumento1, argumento2)
				== 2) {
			output_program("umodes available %s, channel modes available %s",
					argumento1, argumento2);
		}

	} else if (strcmp(palabra, RPL_BOUNCE) == 0) {
		mensaje = strpbrk((ptCaracter + 1), " ");
		ptCaracter = mensaje;
		mensaje = strpbrk((ptCaracter + 1), " ");
		if (mensaje) {
			output_program("%s", (mensaje + 1));
		}

	} else if (strcmp(palabra, RPL_LUSERCLIENT) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		if (mensaje) {
			output_program("%s", (mensaje + 1));
		}

	} else if (strcmp(palabra, RPL_LUSERCHANNELS) == 0) {
		sscanf(ptCaracter, "%*s %*s %s", argumento1);
		mensaje = strpbrk(ptCaracter, ":");
		if (mensaje) {
			output_program("%s %s", argumento1, (mensaje + 1));
		}

	} else if (strcmp(palabra, RPL_LUSERME) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		if (mensaje) {
			output_program("%s", (mensaje + 1));
		}

		/*} else if (strcmp(palabra, RPL_265) == 0) {
		 mensaje = strpbrk((ptCaracter+1), " ");
		 ptCaracter=mensaje;
		 mensaje = strpbrk((ptCaracter+1), " ");
		 if (mensaje) {
		 output_program("%s", (mensaje + 1));
		 }

		 } else if (strcmp(palabra, RPL_266) == 0) {
		 mensaje = strpbrk((ptCaracter+1), " ");
		 ptCaracter=mensaje;
		 mensaje = strpbrk((ptCaracter+1), " ");
		 if (mensaje) {
		 output_program("%s", (mensaje + 1));
		 }
		 */
	} else if (strcmp(palabra, RPL_STATSDLINE) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		if (mensaje) {
			output_program("%s", (mensaje + 1));
		}

	} else if (strcmp(palabra, RPL_MOTDSTART) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		if (mensaje) {
			output_program("%s", (mensaje + 1));
		}

	} else if (strcmp(palabra, RPL_MOTD) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		output_program("%s", (mensaje + 1));

	} else if (strcmp(palabra, RPL_ENDOFMOTD) == 0) {
		//Se ignora

	} else if (strcmp(palabra, RPL_ENDOFNAMES) == 0) {
		//Se ignora

	} else if (strcmp(palabra, RPL_LISTEND) == 0) {
		//Se ignora

	} else if (strcmp(palabra, RPL_ENDOFWHO) == 0) {
		//Se ignora

	} else if (strcmp(palabra, RPL_TOPIC) == 0) {
		sscanf(ptCaracter, "%*s %*s %s", argumento1);
		mensaje = strpbrk(ptCaracter, ":");
		output_program("Topic for %s: %s", argumento1, (mensaje + 1));

	} else if (strcmp(palabra, RPL_NAMREPLY) == 0) {
		sscanf(ptCaracter, "%*s %*s %*s %s", argumento1);
		mensaje = strpbrk(ptCaracter, ":");
		output_program("Users in channel %s: %s", argumento1, (mensaje + 1));

	} else if (strcmp(palabra, RPL_LIST) == 0) {
		sscanf(ptCaracter, "%*s %*s %s %s", argumento1, argumento2);
		mensaje = strpbrk(ptCaracter, ":");
		output_program("%s\t\t%s\t%s", argumento1, argumento2, (mensaje + 1));

	} else if (strcmp(palabra, RPL_WHOREPLY) == 0) {
		sscanf(ptCaracter, "%*s %*s %s %s", argumento1, argumento2);
		if (strcmp(argumento1, channel) == 0) { //Si se encuentra en el mismo canal
			output_program("%s\t\t%s", argumento1, (argumento2 + 1));
		}

		//ERRORES
		//*******
	} else if (strcmp(palabra, ERR_NICKNAMEINUSE) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		output_error("%s", (mensaje + 1));

	} else if (strcmp(palabra, ERR_NOTREGISTERED) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		output_error("%s", (mensaje + 1));

	} else if (palabra[0] == '4') {
		mensaje = strpbrk(ptCaracter, ":");
		output_error("%s", (mensaje + 1));

		//COMANDOS IRC
		//************
	} else if (strcmp(palabra, IRC_JOIN) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		sscanf((mensaje + 1), "%s", argumento1);
		mensaje = strpbrk(servidor, ":");
		ptr = strtok(mensaje, ":!");
		if (ptr) {
			output_program("%s has joined channel %s", ptr, argumento1);
		}
		if (strcmp(ptr, nick) == 0) { //Si habla de nosotros, guardo en que canal estoy
			strcpy(channel, argumento1);
		}

	} else if (strcmp(palabra, IRC_PRIVMSG) == 0) {
		mensaje = strpbrk(servidor, ":");
		ptr = strtok(mensaje, ":!");
		mensaje = strpbrk(ptCaracter, ":");
		if (mensaje[1] == DCC_CODE) { //Mensaje DCC
			if (sscanf((mensaje + 2), "%s", palabra) < 1) {
				output_debug("Mensaje DCC vacio");
			} else {
				if (strcmp(palabra, DCC) == 0) {
					if (sscanf((mensaje + 2), "%*s %s %s %u %d %ld",
							argumento1, argumento2, &ip, &numero, &longitud)
							>= 4) {
						if (strcmp(argumento1, DCC_SEND) == 0) {
							//Obtiene la ip
							ip4 = ip % 256;
							ip = ip / 256;
							ip3 = ip % 256;
							ip = ip / 256;
							ip2 = ip % 256;
							ip = ip / 256;
							ip1 = ip % 256;
							ip = ip / 256;

							//Obtiene el nombre del fichero sin ruta
							strcpy(file_dl_path_temp, argumento2);
							name_file = argumento2;
							temp = strtok(file_dl_path_temp, "/");
							while (temp) {
								name_file = temp;
								temp = strtok(NULL, "/");
							}

							output_program("Download offer from %s", ptr);
							output_program(
									"use \"/download %s %d.%d.%d.%d:%d\" to download",
									name_file, ip1, ip2, ip3, ip4, numero);
						}
					}
				}
			}
		} else {
			output_user(ptr, (mensaje + 1));
		}

	} else if (strcmp(palabra, IRC_PART) == 0) {
		sscanf(ptCaracter, "%*s %s", argumento2);
		mensaje = strpbrk(ptCaracter, ":");
		sscanf((mensaje + 1), "%s", argumento1);
		output_program("%s has left channel %s", argumento1, argumento2);
		if (strcmp(argumento1, nick) == 0) { //Si habla de nosotros, cambiamos el canal a ninguno
			strcpy(channel, "");
		}

	} else if (strcmp(palabra, IRC_QUIT) == 0) {
		mensaje = strpbrk(servidor, ":");
		ptr = strtok(mensaje, ":!");
		if (ptr) {
			if (strcmp(ptr, nick) != 0) { //Si habla de nosotros, se muestra otro mensaje
				output_program("%s has disconnected from server", ptr);
			}
		}

	} else if (strcmp(palabra, IRC_NOTICE) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		output_program("%s", (mensaje + 1));

	} else if (strcmp(palabra, IRC_ERROR) == 0) {
		mensaje = strpbrk(ptCaracter, ":");
		output_program("%s", (mensaje + 1));

		//RESPUESTA DESCONOCIDA
		//*********************
	} else {
		output_program(
				"Message received with a command unknown to RFC2812 (%s)",
				palabra);
	}

	/*Libera servidor*/
	if (servidor)
		free(servidor);

	return 0;
}

void *funcion_escuchas(void *arg) {
	char letra;
	int leido;
	bool *deboMorir;
	char comando[MAX_LONG_IRC_MESSAGE];

	deboMorir = (bool *) arg;

	memset(comando, '\0', MAX_LONG_IRC_MESSAGE);

	output_debug("funcion_hilo: Hilo en ejecucion!");
	while (!state_powerOff && !(*deboMorir)) {
		if (state_sleep > 0) {
			sleep(state_sleep);
		}
		if (socketServer > 0) {
			if ((leido = recibir_mensaje(socketServer, &letra, sizeof(letra)))
					> 0) {
				//output_debug("funcion_escuchas: Leo: %c", letra);
				if (reconstruir_mensaje(comando, letra) > 0) {
					output_debug("funcion_escuchas: Comando: %s|%d|", comando,
							strlen(comando));
					evaluar_comando(comando);
					memset(comando, '\0', MAX_LONG_IRC_MESSAGE);
				}
			} else if (leido < 0) {
				output_debug("funcion_escuchas: Conexion cerrada");
				state_connected = false;
				(*deboMorir) = true;
			}
		} else {
			output_debug("funcion_escuchas: Muero! (socket invalido");
			return NULL;
		}
	}
	output_debug("funcion_escuchas: Muero!");

	return NULL;
}
